package com.lyy.yygh.hosp.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.lyy.cmn.client.DictFeignClient;
import com.lyy.yygh.hosp.repository.HospitalRepository;
import com.lyy.yygh.hosp.service.HospitalService;
import com.lyy.yygh.model.hosp.Hospital;
import com.lyy.yygh.model.hosp.Schedule;
import com.lyy.yygh.vo.hosp.HospitalQueryVo;
import org.apache.logging.log4j.message.ReusableMessage;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

@Service
public class HospitalServiceImpl implements HospitalService {

    /**
     * 创建一个线程池
     */
    private ExecutorService taskExe=
            new ThreadPoolExecutor(10,
                    20,
                    8000L,
                     TimeUnit.MILLISECONDS,
                     new LinkedBlockingQueue<Runnable>(100),
                     Executors.defaultThreadFactory());
    @Autowired
    private HospitalRepository hospitalRepository;

    //注入服务调用Dict
    @Autowired
    private DictFeignClient dictFeignClient;

    /**
     *
     * @param paramap
     */
    @Override
    public void save(Map<String, Object> paramap) {
        //把map集合转化成字符串,先转化成字符串，用到阿里巴巴的依赖
        String mapString = JSONObject.toJSONString(paramap);
        Hospital hospital = JSONObject.parseObject(mapString, Hospital.class);
        //判断是否存在数据
        String hoscode = hospital.getHoscode();
        Hospital hospitalExist = hospitalRepository.getHospitalByHoscode(hoscode);
        System.out.println("是否存在数据"+hospitalExist);
        //如果存在，进行修改
        if (hospitalExist != null) {
            hospital.setStatus(hospitalExist.getStatus());
            hospital.setCreateTime(hospitalExist.getCreateTime());
            hospital.setUpdateTime(new Date());
            hospital.setIsDeleted(0);
            hospitalRepository.save(hospital);

        }
        //如果不存在进行添加
        else {
            hospital.setStatus(0);
            hospital.setCreateTime(new Date());
            hospital.setUpdateTime(new Date());
            hospital.setIsDeleted(0);
            hospitalRepository.save(hospital);
        }
    }

    /**
     * 根据hoscode得到医院
     * @param hoscode
     * @return
     */
    @Override
    public Hospital getByHoscode(String hoscode) {
        Hospital hospitalByHoscode = hospitalRepository.getHospitalByHoscode(hoscode);

        return hospitalByHoscode;
    }

    /**
     * 医院分页列表
     * @param page
     * @param limit
     * @param hospitalQueryVo
     * @return
     */
    @Override
    public Page<Hospital> selectHostPage(Integer page, Integer limit, HospitalQueryVo hospitalQueryVo) {
        Sort sort=Sort.by(Sort.Direction.DESC,"createTime");
        //创建page对象，每页记录数和当前页
        Pageable pageable = PageRequest.of(page - 1, limit);
        //创建example对象
        Hospital hospital = new Hospital();
        BeanUtils.copyProperties(hospitalQueryVo, hospital);
        //schedule.setIsDeleted(0);
        //schedule.setStatus(1);
        ExampleMatcher exampleMatcher = ExampleMatcher.matching()  //构建一个匹配器
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)//改变默认字符串匹配方式：模糊查询
                .withIgnoreCase(true);   //忽略大小写
        //查到所有适合匹配的医院
        Example<Hospital> example=Example.of(hospital,exampleMatcher);
        //分页
        Page<Hospital> all = hospitalRepository.findAll(example, pageable);
        //进行遍历，得到hospital对象，把医院等级封装进去
        all.getContent().stream().forEach(item->{
            this.setHospitalHostype(item);

        });
       // List<Hospital> content = all.getContent();
        return all;
    }

    /**
     * 更新医院上下线状态
     * @param id
     * @param status
     */
    @Override
    public void updateStatus(String id, Integer status) {
        //根据id查询医院信息
        Hospital hospital=hospitalRepository.findById(id).get();
        //设置修改的值
        hospital.setStatus(status);
        hospital.setUpdateTime(new Date());
        hospitalRepository.save(hospital);

    }

    /**
     * 根据医院id得到医院详情页面
     * @param id
     * @return
     */
    @Override
    //医院详情页面
    public Map<String,Object>  getHospById(String id) {

        Map<String,Object> result=new HashMap<>();
        //医院的基本信息
        Hospital hospital = hospitalRepository.findById(id).get();
        System.out.println(hospital);
        try {
            this.setHospitalHosType2(hospital);
        }catch (Exception e){

        }

        result.put("hospital", hospital);
        //预约信息
        result.put("bookingRule", hospital.getBookingRule());
        System.out.println("这儿还走啊");
        return result;
    }

    /**
     * 根据医院编号得到医院名字
     * @param hoscode
     * @return
     */
    @Override
    public String getHospName(String hoscode) {

        Hospital hospitalByHoscode = hospitalRepository.getHospitalByHoscode(hoscode);
        if(hospitalByHoscode!=null){
            return hospitalByHoscode.getHosname();
        }
        return null;
    }

    /**
     * 搜索模糊查询
     * @param hosname
     * @return
     */
    @Override
    public List<Hospital> findByHosname(String hosname) {
        return hospitalRepository.findHospitalByHosnameLike(hosname);

    }


    /**
     * 根据医院编号获取医院编号详情
     * @param hoscode
     * @return
     */
    @Override
    //根据医院编号获取医院编号详情
    public Map<String, Object> item(String hoscode) {
        Map<String, Object> result = new HashMap<>();
        //医院包装
        Hospital hospital = this.setHospitalHostype(this.getByHoscode(hoscode));
        result.put("hospital", hospital);
        //预约规则
        result.put("bookingRule", hospital.getBookingRule());
        //不需要重复返回
        hospital.setBookingRule(null);
        return result;

    }

    /**
     * 包装医院所用【医院等级，医院具体地址】
     * @param item
     * @return
     */
    private Hospital setHospitalHostype(Hospital item) {
        //获取到医院等级名称
        long l = System.currentTimeMillis();
        String hostypeString = dictFeignClient.getname("Hostype", item.getHostype());
        //System.out.println("医院等级是"+hostypeString);
        //调用dict微服务，查询省市区，然后连成一个具体地址
        String Province = dictFeignClient.getname(item.getProvinceCode());
        String City = dictFeignClient.getname(item.getCityCode());
        String District = dictFeignClient.getname(item.getDistrictCode());
        item.getParam().put("fullAddress",Province+City+District);
        item.getParam().put("hostypeString",hostypeString);
        long e=System.currentTimeMillis();
        System.out.println("用时"+(e-l));
        //System.out.println("这儿走不走");
        return item;

    }

    /**
     * FutureTask+线程池实现包装医院
     * @param hospital
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    private Hospital setHospitalHosType(Hospital hospital) throws InterruptedException, ExecutionException {


        long l1 = System.currentTimeMillis();
        //得到类型
        FutureTask getHostypeTask = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                String hostype = dictFeignClient.getname("Hostype", hospital.getHostype());
                return hostype;
            }
        });
        //得到
        FutureTask getProvinceTask = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                String province = dictFeignClient.getname(hospital.getProvinceCode());
                return province;
            }
        });
        FutureTask getCityTask = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                String city =  dictFeignClient.getname(hospital.getCityCode());
                return city;
            }
        });
        FutureTask getDistrictTask = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                String district = dictFeignClient.getname(hospital.getDistrictCode());
                return district;
            }
        });
        taskExe.submit(getHostypeTask);
        taskExe.submit(getProvinceTask);
        taskExe.submit(getCityTask);
        taskExe.submit(getDistrictTask);
        //根据dictCode和value获取医院等级名称
        String hostypeString = (String) getHostypeTask.get();
        //查询 省 市 地区  (多线程优化)
        String provinceString = (String) getProvinceTask.get();
        String cityString = (String) getCityTask.get();
        String districtString = (String) getDistrictTask.get();
        hospital.getParam().put("hostypeString", hostypeString);
        hospital.getParam().put("fullAddress", provinceString + cityString + districtString);
        long l2 = System.currentTimeMillis();
        System.out.println("线程池用时"+(l2-l1));
        return hospital;
    }
    public static ExecutorService service=Executors.newFixedThreadPool(10);

    private Hospital setHospitalHosType2(Hospital hospital) throws ExecutionException, InterruptedException {
        long l1 = System.currentTimeMillis();
        CompletableFuture<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {
            String hostype = dictFeignClient.getname("Hostype", hospital.getHostype());
            return hostype;
        }, service);
        CompletableFuture<String> completableFuture2 = CompletableFuture.supplyAsync(() -> {
            String province = dictFeignClient.getname(hospital.getProvinceCode());
            return province;
        }, service);
        CompletableFuture<String> completableFuture3 = CompletableFuture.supplyAsync(() -> {
            String city =  dictFeignClient.getname(hospital.getCityCode());
            return city;
        }, service);
        CompletableFuture<String> completableFuture4 = CompletableFuture.supplyAsync(() -> {
            String district = dictFeignClient.getname(hospital.getDistrictCode());
            return district;
        }, service);

        CompletableFuture.allOf(completableFuture1,completableFuture2,completableFuture3,completableFuture4);
        String hostypeString = (String) completableFuture1.get();
        String provinceString = (String) completableFuture2.get();
        String cityString = (String) completableFuture3.get();
        String districtString = (String) completableFuture4.get();
        hospital.getParam().put("hostypeString", hostypeString);
        hospital.getParam().put("fullAddress", provinceString + cityString + districtString);
        long l2 = System.currentTimeMillis();
        System.out.println("编排线程池用时"+(l2-l1));
        return hospital;
    }
}
